
/**
  ******************************************************************************
  * Copyright 2021 The Microbee Authors. All Rights Reserved.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  * 
  * @file       sim_frame.h
  * @author     baiyang
  * @date       2022-11-29
  ******************************************************************************
  */

#pragma once

#ifdef __cplusplus
extern "C"{
#endif

/*----------------------------------include-----------------------------------*/
#include "sim_aircraft.h"
#include "sim_motor.h"
/*-----------------------------------macro------------------------------------*/

/*----------------------------------typedef-----------------------------------*/
typedef struct sim_frame* sim_frame_t;
typedef const struct sim_frame* sim_frame_const_t;

struct FrameModel {
    // model mass kg
    float mass;

    // diameter of model
    float diagonal_size;

    /*
      the ref values are for a test at fixed angle, used to estimate drag
     */
    float refSpd; // m/s
    float refAngle;  // degrees
    float refVoltage; // Volts
    float refCurrent; // Amps
    float refAlt; // altitude AMSL
    float refTempC; // temperature C
    float refBatRes; // BAT.Res

    // full pack voltage
    float maxVoltage;

    // battery capacity in Ah. Use zero for unlimited
    float battCapacityAh;

    // CTUN.ThO at hover at refAlt
    float hoverThrOut;

    // MOT_THST_EXPO
    float propExpo;

    // scaling factor for yaw response, deg/sec
    float refRotRate;

    // MOT params are from the reference test
    // MOT_PWM_MIN
    float pwmMin;
    // MOT_PWM_MAX
    float pwmMax;
    // MOT_SPIN_MIN
    float spin_min;
    // MOT_SPIN_MAX
    float spin_max;

    // maximum slew rate of motors
    float slew_max;

    // rotor disc area in m**2 for 4 x 0.35m dia rotors
    // Note that coaxial rotors count as one rotor only when calculating effective disc area
    float disc_area;

    // momentum drag coefficient
    float mdrag_coef;

    // if zero value will be estimated from mass
    Vector3f_t moment_of_inertia;

    // if zero will no be used
    Vector3f_t motor_pos[12];
    Vector3f_t motor_thrust_vec[12];
    float yaw_factor[12];

    // number of motors
    float num_motors;
} ;

struct sim_frame {
    const char *name;
    uint8_t num_motors;
    sim_motor_t motors;

    float terminal_velocity;
    float terminal_rotation_rate;
    uint8_t motor_offset;

    struct FrameModel model;

    // exposed area times coefficient of drag
    float areaCd;
    float mass;
    float last_param_voltage;
    sim_battery_t battery;
};
/*----------------------------------variable----------------------------------*/

/*-------------------------------------os-------------------------------------*/

/*----------------------------------function----------------------------------*/
// find a frame by name
sim_frame_t sim_frame_find_frame(const char *name);

// initialise the frame
void sim_frame_init(sim_frame_t frame, const char *frame_str, sim_battery_t _battery);

// get air density in kg/m^3
float sim_frame_get_air_density(sim_frame_const_t frame, float alt_amsl);

// calculate rotational and linear accelerations
// bool use_drag=true
void sim_frame_calculate_forces(sim_frame_t frame, sim_aircraft_const_t aircraft,
                             const struct sitl_input *input,
                             Vector3f_t *rot_accel,
                             Vector3f_t *body_accel,
                             float* rpm,
                             bool use_drag);

// calculate current and voltage
void sim_frame_current_and_voltage(sim_frame_t frame, float *voltage, float *current);

// get mass in kg
static inline float sim_frame_get_mass(sim_frame_const_t frame) {
    return frame->mass;
}

// set mass in kg
static inline void sim_frame_set_mass(sim_frame_t frame, float new_mass) {
    frame->mass = new_mass;
}
/*------------------------------------test------------------------------------*/

#ifdef __cplusplus
}
#endif



